﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace TuKu
{
    #region 下载任务管理器

    /// <summary>
    /// 下载任务管理器
    /// 主要功能：数据统计、任务管理、任务/队列/线程初始化
    /// [重要：断点续传]任务列表信息保存、载入
    /// [重要：事件处理]下载过程中的内部事件处理
    /// </summary>
    public class DTaskMag
    {
        /// <summary>
        /// 初始化下载任务管理器
        /// </summary>
        public DTaskMag()
        {
            m_TaskList = new List<DTask>();
            m_TaskDataList = new DTaskDataList();
            m_TaskListControl = new TaskListControl();
            m_EventProxy = new EventProxy();
        }
        /// <summary>
        /// 初始化下载任务管理器
        /// </summary>
        /// <param name="taskListFileName">下载列表信息文件</param>
        public DTaskMag(string taskListFileName)
        {
            m_TaskListFile = taskListFileName;
            m_TaskList = new List<DTask>();
            m_TaskDataList = new DTaskDataList();
            m_TaskListControl = new TaskListControl();
            m_EventProxy = new EventProxy();
        }

        #region 静态变量

        private static int s_MaxErrorCount = 100 * 1024;
        private static int s_MinSize = 9;
        /// <summary>
        /// 线程最大错误次数
        /// </summary>
        public static int MaxErrorCount
        {
            get { return DTaskMag.s_MaxErrorCount; }
            set { DTaskMag.s_MaxErrorCount = value; }
        }
        /// <summary>
        /// 多线程下载最小分块
        /// </summary>
        public static int MinSize
        {
            get { return DTaskMag.s_MinSize; }
            set { DTaskMag.s_MinSize = value; }
        }

        #endregion

        #region 属性

        private bool m_hodding;
        private long m_MemoryCount;
        private long m_TotleCount;
        private long m_CurCount;
        private string m_TaskListFile;
        private List<DTask> m_TaskList;
        private DTaskDataList m_TaskDataList;
        private TaskListControl m_TaskListControl;
        private EventProxy m_EventProxy;
        /// <summary>
        /// 获取当前事件代理对象
        /// </summary>
        internal EventProxy EventProxy
        {
            get { return m_EventProxy; }
        }
        /// <summary>
        /// 事件 线程同步锁
        /// </summary>
        private readonly Object m_taskListFileLock = new Object();
        /// <summary>
        /// 文件 线程同步锁
        /// </summary>
        private readonly Object m_taskFileLock = new Object();

        /// <summary>
        /// 获取当前 任务列表
        /// （包括所有状态的任务对象）
        /// </summary>
        public List<DTask> TaskList
        {
            get { return m_TaskList; }
        }

        /// <summary>
        /// 获取当前 下载任务队列控制器
        /// </summary>
        public TaskListControl TaskListControl
        {
            get
            {
                if (m_TaskListControl == null)
                {
                    m_TaskListControl = new TaskListControl();
                }
                return m_TaskListControl;
            }
        }

        /// <summary>
        /// 获取/设置 下载等待状态（限速标志）
        /// </summary>
        public bool Hodding
        {
            get { return m_hodding; }
            set { m_hodding = value; }
        }
        /// <summary>
        /// 获取 缓存数据大小
        /// </summary>
        public long MemoryCount
        {
            get { return m_MemoryCount; }
        }
        /// <summary>
        /// 获取 已下载数据大小
        /// </summary>
        public long TotleCount
        {
            get { return m_TotleCount; }
        }
        /// <summary>
        /// 设置/获取 单位时间内下载数据大小
        /// </summary>
        public long CurCount
        {
            get { return m_CurCount; }
            set { m_CurCount = value; }
        }

        /// <summary>
        /// 获取 任务列表文件完整路径
        /// </summary>
        public string TaskListFile
        {
            get { return m_TaskListFile; }
        }

        #endregion

        #region 保存、导入 任务列表
        /// <summary>
        /// 导入 任务列表
        /// </summary>
        /// <param name="taskListFileName"></param>
        public void LoadTaskList(string taskListFileName)
        {
            m_TaskListFile = taskListFileName;
            LoadTaskList();
        }
        /// <summary>
        /// 导入 任务列表
        /// </summary>
        public void LoadTaskList()
        {
            if (m_TaskListFile != null && m_TaskListFile.Length > 0)
            {
                doLoadTaskList(m_TaskListFile);
                TaskListInit();
            }
        }
        private void TaskListInit()
        {
            TaskListControl.Clear();
            foreach (DTask task in m_TaskList)
            {
                TaskInit(task);
                TaskListControl.AutoAdd(task);
            }
        }


        /// <summary>
        /// 保存 任务列表
        /// </summary>
        public void SaveTaskList()
        {
            if (m_TaskListFile != null && m_TaskListFile.Length > 0)
            {
                doSaveTaskList(m_TaskListFile);
            }
        }
        /// <summary>
        /// 保存 任务列表
        /// </summary>
        /// <param name="taskListFileName">下载列表文件</param>
        public void SaveTaskList(string taskListFileName)
        {
            m_TaskListFile = taskListFileName;
            SaveTaskList();
        }

        /// <summary>
        /// 保存 任务列表
        /// </summary>
        /// <param name="filename"></param>
        protected internal void doSaveTaskList(string fileName)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(DTaskDataList));
            lock (m_taskListFileLock)
            {
                FileStream stream = new FileStream(fileName, FileMode.Create);
                DTaskDataList tmp = m_TaskDataList;
                serializer.Serialize(stream, tmp);
                stream.Close();
            }
        }
        /// <summary>
        /// 载入 任务列表
        /// </summary>
        /// <param name="filename"></param>
        protected internal void doLoadTaskList(string fileName)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(DTaskDataList));
            FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            m_TaskDataList = (DTaskDataList)serializer.Deserialize(stream);
            stream.Close();
            foreach (DTaskData taskData in m_TaskDataList.TaskDataList)
            {
                this.Add(taskData);
            }
        }

        /// <summary>
        /// 保存 任务
        /// </summary>
        /// <param name="task"></param>
        public void SaveTask(DTask task)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(DTaskData));
            lock (m_taskFileLock)
            {
                FileStream stream = new FileStream(task.ConfigFileName, FileMode.Create);
                serializer.Serialize(stream, task.TaskData);
                stream.Close();
            }
        }
        /// <summary>
        /// 载入 任务
        /// </summary>
        /// <param name="filename"></param>
        public DTask LoadTask(string filename)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(DTaskData));
            FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            DTask task = new DTask(this, (DTaskData)serializer.Deserialize(stream));
            stream.Close();
            return task;
        }

        #endregion

        #region 任务控制

        /// <summary>
        /// 立即将所有下载任务缓存中的数据写入文件
        /// </summary>
        public void WriteToFiles()
        {
            foreach (DTask dt in m_TaskList)
            {
                dt.WriteToFile();
            }
        }

        /// <summary>
        /// 往现有 任务列表 中添加一个任务
        /// </summary>
        /// <param name="taskData">下载任务</param>
        public void Add(DTaskData taskData)
        {
            DTask task = new DTask(this, taskData);
            TaskInit(task);
            if (!m_TaskDataList.TaskDataList.Contains(taskData))
            {
                m_TaskDataList.TaskDataList.Add(taskData);
            }
            m_TaskList.Add(task);
            m_TaskListControl.AutoAdd(task);
        }

        private void TaskInit(DTask task)
        {
            if (task.TaskMag.Equals(this))
            {
                if (!task.IsInitialized)
                {
                    task.TaskCompleted += this.onTaskCompleted;
                    task.TaskFailed += this.onTaskFailed;
                    task.TaskStopped += this.onTaskStopped;
                    task.TaskStarted += this.onTaskStarted;
                    task.TaskAborted += this.onTaskAborted;
                    task.TaskWriteToMemoryStream += this.onTaskWriteToMemoryStream;
                    task.TaskWriteToFileStream += this.onTaskWriteToFileStream;
                    task.TaskError += this.onTaskError;
                    task.TaskStateChanged += this.onTaskStateChanged;
                    task.TaskThreadInitialized += this.onTaskThreadInitialized;
                    task.IsInitialized = true;
                }
            }
        }

        #endregion

        #region 事件

        private event EventHandler<DTaskEventArgs> e_TaskCompleted;
        /// <summary>
        /// 文件（任务）下载完成事件
        /// </summary>
        public event EventHandler<DTaskEventArgs> TaskCompleted
        {
            add { e_TaskCompleted += value; }
            remove { e_TaskCompleted -= value; }
        }

        private event EventHandler<DTaskEventArgs> e_TaskFailed;
        /// <summary>
        /// 文件（任务）下载失败事件
        /// </summary>
        public event EventHandler<DTaskEventArgs> TaskFailed
        {
            add { e_TaskFailed += value; }
            remove { e_TaskFailed -= value; }
        }

        private event EventHandler<DTaskEventArgs> e_TaskStarted;
        /// <summary>
        /// 文件（任务）下载开始事件
        /// </summary>
        public event EventHandler<DTaskEventArgs> TaskStarted
        {
            add { e_TaskStarted += value; }
            remove { e_TaskStarted -= value; }
        }

        private event EventHandler<DTaskEventArgs> e_TaskStopped;
        /// <summary>
        /// 文件（任务）下载停止事件
        /// </summary>
        public event EventHandler<DTaskEventArgs> TaskStopped
        {
            add { e_TaskStopped += value; }
            remove { e_TaskStopped -= value; }
        }

        private event EventHandler<DTaskEventArgs> e_TaskAborted;
        /// <summary>
        /// 文件（任务）下载取消事件
        /// </summary>
        public event EventHandler<DTaskEventArgs> TaskAborted
        {
            add { e_TaskAborted += value; }
            remove { e_TaskAborted -= value; }
        }

        private event EventHandler<TaskErrorEventArgs> e_TaskError;
        /// <summary>
        /// 下载错误事件
        /// </summary>
        public event EventHandler<TaskErrorEventArgs> TaskError
        {
            add { e_TaskError += value; }
            remove { e_TaskError -= value; }
        }

        private event EventHandler<TaskStateChangedEventArgs> e_TaskStateChanged;
        /// <summary>
        /// 任务状态变更事件
        /// </summary>
        public event EventHandler<TaskStateChangedEventArgs> TaskStateChanged
        {
            add { e_TaskStateChanged += value; }
            remove { e_TaskStateChanged -= value; }
        }

        private event EventHandler<TaskInitializedEventArgs> e_TaskInitialized;
        /// <summary>
        /// 任务状态变更事件
        /// </summary>
        public event EventHandler<TaskInitializedEventArgs> TaskInitialized
        {
            add { e_TaskInitialized += value; }
            remove { e_TaskInitialized -= value; }
        }

        #endregion

        #region 事件处理
        /// <summary>
        /// 处理 文件写入 事件
        /// </summary>
        /// <param name="sender">触发事件的任务</param>
        /// <param name="e"></param>
        private void onTaskWriteToFileStream(object sender, WriteToStreamEventArgs e)
        {
            m_MemoryCount -= e.Length;

            // 保存当前任务下载状态
            this.SaveTaskList();
            this.SaveTask((DTask)sender);
        }
        /// <summary>
        /// 处理 内存缓存写入 事件
        /// </summary>
        /// <param name="sender">触发事件的任务</param>
        /// <param name="e"></param>
        private void onTaskWriteToMemoryStream(object sender, WriteToStreamEventArgs e)
        {
            m_CurCount += e.Length;
            m_MemoryCount += e.Length;
            m_TotleCount += e.Length;
        }
        /// <summary>
        /// 处理 任务完成 事件
        /// </summary>
        /// <param name="sender">触发事件的任务</param>
        /// <param name="e"></param>
        private void onTaskCompleted(object sender, DTaskEventArgs e)
        {
            if (e_TaskCompleted != null && !e.Cancel)
            {
                e_TaskCompleted(sender, e);
            }
            // 将任务对象添加到已完成的任务队列，等待任务管理器处理
            m_TaskListControl.FinishTask((DTask)sender);
        }
        /// <summary>
        /// 处理 任务失败 事件
        /// </summary>
        /// <param name="sender">触发事件的任务</param>
        /// <param name="e"></param>
        private void onTaskFailed(object sender, DTaskEventArgs e)
        {
            if (e_TaskFailed != null && !e.Cancel)
            {
                e_TaskFailed(sender, e);
            }
        }

        /// <summary>
        /// 处理 下载错误 事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal void onTaskError(object sender, TaskErrorEventArgs e)
        {
            // 加入重试队列
            m_TaskListControl.AddWaitingWorkThread(e.ErrorThread);
            if (e_TaskError != null)
            {
                e_TaskError(sender, e);
            }
        }

        private void onTaskStarted(object sender, DTaskEventArgs e)
        {
            if (e_TaskStarted != null && !e.Cancel)
            {
                e_TaskStarted(sender, e);
            }
        }

        private void onTaskStopped(object sender, DTaskEventArgs e)
        {
            if (e_TaskStopped != null && !e.Cancel)
            {
                e_TaskStopped(sender, e);
            }
        }

        private void onTaskAborted(object sender, DTaskEventArgs e)
        {
            DTask task = (DTask)sender;
            // 从任务列表删除
            m_TaskList.Remove(task);
            m_TaskDataList.TaskDataList.Remove(task.TaskData);

            if (e_TaskAborted != null && !e.Cancel)
            {
                e_TaskAborted(sender, e);
            }
        }

        /// <summary>
        /// 处理 任务状态变更 事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void onTaskStateChanged(object sender, TaskStateChangedEventArgs e)
        {
            if (e_TaskStateChanged != null && !e.Cancel)
            {
                e_TaskStateChanged(sender, e);
            }
            // 重要：此处处理所有状态变更后任务队列的变更
            m_TaskListControl.AutoAdd((DTask)sender);
        }

        /// <summary>
        /// 处理任务线程初始化完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void onTaskThreadInitialized(object sender, TaskInitializedEventArgs e)
        {
            if (e_TaskInitialized != null)
            {
                e_TaskInitialized(sender, e);
            }
            // 保存当前任务下载状态
            this.SaveTaskList();
            this.SaveTask((DTask)sender);
        }

        #endregion
    }

    #endregion
}
